package handler

import (
	"context"
	"fmt"
	"go.uber.org/zap"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"google.golang.org/protobuf/types/known/emptypb"
	"rpc_demo/stock_srv/global"
	"rpc_demo/stock_srv/model"
	"rpc_demo/stock_srv/proto"
	"rpc_demo/stock_srv/utils/register"
)

type StockSrv struct {
	proto.UnimplementedStocksServer
}

func (s *StockSrv) SetStocks(ctx context.Context, req *proto.GoodsStockInfo) (*emptypb.Empty, error) {

	var stock model.Stock

	global.Db.Where(&model.Stock{Goods: req.GoodsId}).First(&stock)
	stock.Goods = req.GoodsId
	stock.Stocks = req.Num
	global.Db.Where(&model.Stock{Goods: req.GoodsId}).Save(&stock)
	return &emptypb.Empty{}, nil
}

func (s *StockSrv) StocksDetail(ctx context.Context, req *proto.GoodsStockInfo) (*proto.GoodsStockInfo, error) {
	var stock model.Stock
	if res := global.Db.Where(&model.Stock{Goods: req.GoodsId}).First(&stock); res.RowsAffected == 0 {
		zap.S().Error(codes.NotFound, "库存信息不存在")
		return nil, status.Errorf(codes.NotFound, "库存信息不存在")
	}

	return &proto.GoodsStockInfo{
		GoodsId: stock.Goods,
		Num:     stock.Stocks,
	}, nil
}

//var lock sync.Mutex

func (s *StockSrv) Sell(ctx context.Context, req *proto.SellInfo) (*emptypb.Empty, error) {

	redSync := register.New("localhost", 6379)

	goodsIds := []int32{}

	tx := global.Db.Begin()
	//lock.Lock()

	//todo 先拼接商品id, 在统一查询商品库存
	for _, goodsInfo := range req.GoodsInfo {
		mutexname := fmt.Sprintf("goods-%d", goodsInfo.GoodsId)
		mutex := redSync.Redsync.NewMutex(mutexname)

		if err := mutex.Lock(); err != nil {
			fmt.Println("获取锁失败")
			zap.S().Error(codes.Internal, "获取锁失败")
		}
		var stock model.Stock
		goodsIds = append(goodsIds, goodsInfo.GoodsId)
		if res := tx.Where(&model.Stock{Goods: goodsInfo.GoodsId}).First(&stock); res.RowsAffected == 0 {
			zap.S().Error(codes.NotFound, "库存信息不存在")
			tx.Rollback()
			return nil, status.Errorf(codes.NotFound, "库存信息不存在")
		}

		if stock.Stocks < goodsInfo.Num {
			fmt.Println("库存不足")
			tx.Rollback()
			return nil, status.Errorf(codes.NotFound, "库存不足")
		}
		stock.Stocks -= goodsInfo.Num
		tx.Save(&stock)
		if ok, err := mutex.Unlock(); !ok || err != nil {
			fmt.Println("锁释放失败")
			return nil, status.Errorf(codes.Internal, "锁释放失败")
		}

	}
	tx.Commit()
	//lock.Unlock()
	return &emptypb.Empty{}, nil
}

func (s *StockSrv) Reback(ctx context.Context, req *proto.SellInfo) (*emptypb.Empty, error) {
	var stock model.Stock

	goodsIds := []int32{}

	tx := global.Db.Begin()

	//todo 先拼接商品id, 在统一查询商品库存
	for _, goodsInfo := range req.GoodsInfo {
		goodsIds = append(goodsIds, goodsInfo.GoodsId)
		if res := tx.Where(&model.Stock{Goods: goodsInfo.GoodsId}).First(&stock); res.RowsAffected == 0 {
			zap.S().Error(codes.NotFound, "库存信息不存在")
			tx.Rollback()
			return nil, status.Errorf(codes.NotFound, "库存信息不存在")
		}
		stock.Stocks += goodsInfo.Num
		tx.Save(&stock)
	}
	tx.Commit()
	return &emptypb.Empty{}, nil
}
